/************************************************************************

								Heroes IV
					  Copyright 2000, The 3DO Company

	------------------------------------------------------------------
  						       combat_window.h

	$Header: /game/combat_window.h $

	$NoKeywords: $

 ************************************************************************/

#if !defined( COMBAT_WINDOW_H_INCLUDED )
#define COMBAT_WINDOW_H_INCLUDED

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

#include <list>
#include <memory>
#include <vector>
#include "adv_map_point.h"
#include "army_ptr.h"
#include "battlefield_ptr.h"
#include "bitmap_group_ptr.h"
#include "combat_action_message.h"
#include "combat_context_ptr.h"
#include "combat_cursor_mode.h"
#include "combat_result.h"
#include "counted_thread_safe_ptr.h"
#include "creature_array.h"
#include "game_window.h"
#include "map_point.h"

class  t_abstract_combat_object;
class  t_army;
class  t_battlefield_window;
class  t_battlefield_terrain_map;
class  t_bitmap_layer_window;
class  t_button;
class  t_combat_action_message_displayer;
class  t_combat_creature;
class  t_combat_creature_icon;
class  t_hero;
class  t_ownable_garrisonable_adv_object;
class  t_player;
enum   t_player_color;
class  t_spell_icon_window;
class  t_saved_combat;
class  t_text_window;
class  t_toggle_button;
class  t_town;

// -----------------------------------------------------------------------
// t_combat_window class
// -----------------------------------------------------------------------

class t_combat_window : public t_window
{
public:
	// Constructor/Destructor
	explicit t_combat_window( t_combat_context* context, t_window* parent );
	explicit t_combat_window( t_saved_combat& saved_combat, t_window* parent );
	virtual ~t_combat_window();

	bool                attacker_lost() const;
	bool				attacker_won() const;
	bool				defender_won() const;
	void				display_creature_action( t_combat_action_message_displayer & displayer, 
												 t_combat_action_message const & message );
	void				display_creature_ready( t_combat_creature const * creature );
	void				enable_all_buttons( bool arg );
	void				enable_auto_combat( bool arg );
	void				enable_cancel_spell( bool arg );
	void				enable_cast_spell( bool arg );
	void				enable_options( bool arg );
	void				enable_wait( bool arg );
	void				end_displayed_creature_action( t_combat_action_message_displayer & displayer );
	t_town*				find_nearest_town( bool defender, 
										   bool & enemy_adjacent_towns_found,
										   bool & blocked_towns_found,
										   t_adv_map_point * location = NULL,
										   bool*  nearby_town_found = 0 ) const;
	void				force_combat_termination( t_combat_result result );
	t_combat_context_ptr						get_context() const;
	t_battlefield_ptr							get_battlefield();
	t_battlefield_window *						get_battlefield_window();
	t_army_ptr									get_new_army_ptr();
	t_combat_result								get_result() const;
	t_battlefield_terrain_map*					get_terrain_map();
	void				load_game();
	virtual bool		menu_click( int id );	
	void				new_game();
	virtual void        on_close();
	void				quit();
	bool				save_game();
	void				set_new_army_ptr( t_army_ptr & new_army_ptr );
	void				set_cursor_mode( t_combat_cursor_mode mode );
	void				set_result( t_combat_result result );
	void				show_cancel_spell_button( bool arg );
	void				start();

private:
	enum
	{
		k_max_spell_icons = 4
	};

	typedef std::list< t_combat_action_message_displayer* > t_combat_action_message_displayer_list;

	void auto_combat_click( t_button* button );
	void cancel_spell_click( t_button* button );
	void cast_spell_click( t_button* button );
	void create_battlefield();
	void create_buttons( t_window* background );
	void create_displays( t_window* background );
	void defend_click( t_button* button );
	void initialize();
	void melee_click( t_button* button );
	void options_click( t_button* button );
	void place_combatants();
	void retreat_click( t_button* button );
	void surrender_click( t_button* button );
	void update_status_icons();
	void wait_click( t_button* button );

	// Data members
	t_combat_action_message_displayer_list		m_action_displayer_list;
	t_combat_action_message						m_action_message;
	t_text_window*								m_action_text_window;
	t_spell_icon_window*						m_active_spells[k_max_spell_icons];
	t_toggle_button*							m_auto_combat_button;
	t_battlefield_ptr							m_battlefield;
	t_battlefield_window*						m_battlefield_window;
	t_bitmap_group_ptr							m_bitmaps;
	t_button*									m_cancel_spell_button;
	t_button*									m_cast_spell_button;
	t_button*									m_combat_mode_button[k_combat_mode_count];
	t_combat_context_ptr						m_context;
	t_combat_creature_icon*						m_creature_icon;
	t_button*									m_defend_button;
	t_bitmap_layer_window*						m_health_icon;
	t_text_window*								m_health_text;
	t_army_ptr									m_new_army_ptr; // Army created by post_process_apply_combat_results()
	t_button*									m_options_button;
	t_counted_const_ptr<t_combat_creature>		m_ready_creature;
	t_combat_result								m_result;
	t_button*									m_retreat_button;
	t_bitmap_layer_window*						m_shots_icon;
	t_text_window*								m_shots_text;
	t_bitmap_layer_window*						m_spell_points_icon;
	t_text_window*								m_spell_points_text;
	t_button*									m_surrender_button;
	t_counted_ptr<t_battlefield_terrain_map>	m_terrain_map;
	t_button*									m_wait_button;
};

inline t_battlefield_ptr t_combat_window::get_battlefield()
{
	return m_battlefield;
}

inline bool t_combat_window::attacker_lost() const
{
	return ::attacker_lost( m_result );
}

inline bool t_combat_window::attacker_won() const
{
	return ::attacker_won( m_result );
}

inline bool t_combat_window::defender_won() const
{
	return ::defender_won( m_result );
}

inline t_battlefield_window * t_combat_window::get_battlefield_window()
{
	return m_battlefield_window;
}

inline t_combat_context_ptr t_combat_window::get_context() const
{
	return m_context;
}

inline t_combat_result t_combat_window::get_result() const
{
	return m_result;
}

inline void t_combat_window::set_result( t_combat_result result )
{
	m_result = result;
}

#endif // !defined( COMBAT_WINDOW_H_INCLUDED )
